<?php
/*------------------------------------------
* @AUTHOR: TANDAT @EMAIL:tidusvn05@gmail.com
* @PHONE: +84933731173
* -----------------------------------------*/

/*------------------------------------------
* Cassandra model abstract
* -----------------------------------------*/
use cassandra\IndexOperator;

use phpcassa\CassandraUtil;

use phpcassa\ColumnSlice;

use phpcassa\ColumnFamily;
use phpcassa\Connection\ConnectionPool;
use phpcassa\SystemManager;
use phpcassa\UUID;

class D_Cassandra_Abstract {
	/**
	 * Default Zend_Db_Adapter_Abstract object.
	 *
	 * @var D_Cassandra_Abstract
	 */
	protected static $_sys;
	protected static $_pool;
	protected $_colunm_family = "";
	protected $_class_name = "";
	protected $_cf;
	
	public static function factory($dbs){
		self::$_sys = new SystemManager( $dbs->host );
		self::$_pool = new ConnectionPool($dbs->name, array($dbs->host));
		self::logging("Init Db Cassandra {$dbs->name}");
	}
	
	public function __construct(){
		$class_name = get_called_class();
		
		if($class_name != 'D_Cassandra_Abstract'){
			if($this->_colunm_family == ''){
				//Auto connect pool
				$this->_cf = new ColumnFamily(self::$_pool, $class_name);
			}else{
				//Manual connect pool
				$this->_cf = new ColumnFamily(self::$_pool, $this->_colunm_family);
			}
		}
	}
	
	public function all_keys(){
		$rows = $this->get_rows();
		$results = array();
		foreach ($rows as $key=>$value){
			$results[] = $key;
		}
		return $results;
	}
	
	
	// insert data
	public function insert($key, $data){
		//$data['created_at'] = microtime(true);
		//$data['updated_at'] = microtime(true);
		$this->_cf->insert($key, $data);
		$this->inscrease_count();
	}
	
	public function batch_insert($array_data){
		$datas = array();
		foreach ($array_data as $key => $value){
			$value['created_at'] = microtime(true);
			$value['updated_at'] = microtime(true);
			$datas[$key] = $value;
		}
		
		$this->_cf->batch_insert($datas);
	}
	
	//get row by single key
	public function get($key){
		return $this->_cf->get($key);
	}
	// get row by many key
	public function multiget($keys){
		return $this->_cf->multiget($keys);
	}
	
	// Get row and only get colunms by range
	public function get_with_colunm_in_range($key, $from='', $to='', $count=0, $reversed = false){
		if($count==0){
			$count = ColumnFamily::DEFAULT_ROW_COUNT;
		}
		$slice = new ColumnSlice($from, $to, $count, $reversed);
		return $this->_cf->get( 'key', $slice);
	}
	
	public function get_with_colunm_from($key, $from, $count=0){
		return $this->get_with_colunm_in_range($key, $from, '', $count);
	}
	
	public function get_with_colunm_to($key, $to, $count=0){
		return $this->get_with_colunm_in_range($key, '', $to, $count);
	}
	
	/*
	 * GET Multi rows
	 * methods: get_all, 
	 * 
	 */
	public function get_rows(){
		return $this->_cf->get_range();
	}
	
	public function get_rows_from($key_start, $count=0){
		if($count==0){
			$count = ColumnFamily::DEFAULT_ROW_COUNT;
		}
		return $this->_cf->get_range($key_start, "", $count);
	}
	
	// remove row
	public function remove($key){
		$this->_cf->remove($key);
	}
	
	// remove all row in column family
	public function truncate(){
		$this->_cf->truncate();
	}
	
	/*
	 * INDEX
	 * 
	 */
	public function create_index($column_name, $type="UTF8Type"){
		$colunm_family_name = get_called_class();
		$config = Zend_Registry::getInstance()->get("config");
		self::$_sys->create_index($config->db->name, $colunm_family_name, $column_name, $type);
		$this->logging("created index: {$column_name}");
	}
	
	public function get_rows_by_index($colunmn_name, $value, $operator=IndexOperator::EQ, $start_key='', $count=100 ){
		$arr_index_expression[] = CassandraUtil::create_index_expression($colunmn_name , $value, $operator);
		$index_clause = CassandraUtil::create_index_clause($arr_index_expression, $start_key, $count);
		return $this->_cf->get_indexed_slices($index_clause);
	}
	

	/*
	 * COUNT
	 * 
	 */
	public function count(){
		$colunm_family_name = get_called_class();
		$count = new Count();
		try{
			$row = $count->get($colunm_family_name);
			return $row['count'];
		}catch (Exception $e){
			$count->insert($colunm_family_name, array('count' => 0));
			return 0;
		}
	}
	
	public function inscrease_count(){
		$colunm_family_name = get_called_class();
		$count = new Count();
		try{
			$row = $count->get($colunm_family_name);
			$row['count'] = $row['count'] + 1;
			$count->getCF()->insert($colunm_family_name, $row);
			return $row['count'] + 1;
		}catch (Exception $e){
			$count->getCF()->insert($colunm_family_name, array('count' => 1));
			return 1;
		}
	}
	
	public function update_count(){
		$all_rows = $this->get_rows();
		$i = 0;
		foreach ($all_rows as $key=>$value){
			$i ++;
		}
		//update count
		$colunm_family_name = get_called_class();
		$count = new Count();
		$count->insert($colunm_family_name, array('count' => $i));
	}
	
	/*
	 * TOOL
	 */
	public function generateID(){
		return UUID::uuid1();
	}
	
	
	//get a colunm family
	public function getCF(){
		return $this->_cf; 
	}
	
	public static function getSys(){
		return self::$_sys;
	}
	
	public static function logging($msg, $type=Zend_Log::INFO){
		$writer = new Zend_Log_Writer_Stream('./log/cassandra.log');
		$logger = new Zend_Log($writer);
		$logger->log($msg, $type);
	}

	
	
}

?>